home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / netconf / rarp.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  11KB  |  494 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include "netconf.h"
  6. #include <netdb.h>
  7. #include "../userconf/userconf.h"
  8. #include "netconf.m"
  9.  
  10. static NETCONF_HELP_FILE help_rarp ("rarp");
  11. static CONFIG_FILE f_net_rarp (PROC_NET_RARP
  12.     ,help_rarp
  13.     ,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
  14.  
  15.  
  16. class RARP_ENTRY: public ARRAY_OBJ{
  17. public:
  18.     char seen;    // Used to tell if one entry has been
  19.                         // processed
  20.     char active;        // This record has to be activated in the kernel
  21.     SSTRING ip;            // IP number of host name
  22.     SSTRING hw;            // Hardware address
  23.     SSTRING comment;
  24.     /*~PROTOBEG~ RARP_ENTRY */
  25. public:
  26.     RARP_ENTRY (const char *_ip,
  27.          const char *_hw,
  28.          int _active,
  29.          const char *_comment);
  30.     RARP_ENTRY (const char *str, int noline);
  31.     RARP_ENTRY (void);
  32.     int cmp (const char *ipstr);
  33.     int edit (void);
  34.     int is_valid (int talk);
  35. private:
  36.     int normalise (void);
  37. public:
  38.     int set (void);
  39.     int unset (void);
  40.     /*~PROTOEND~ RARP_ENTRY */
  41. };
  42. /*
  43.     Constructor used to read /proc/net/rarp
  44. */
  45. PUBLIC RARP_ENTRY::RARP_ENTRY(const char *str, int noline)
  46. {
  47.     active = 1;
  48.     seen = 0;
  49.     char ipstr[100];
  50.     char mbps[100];
  51.     char ethernet[100];
  52.     char hwstr[100];
  53.     /* #Specification: rarp / proc/net/rarp / format
  54.         We assume this file has the following format
  55.         and are simply looking for 4 words.
  56.  
  57.         #
  58.         ip_number    10Mbps Ethernet    hw_address
  59.         #
  60.  
  61.         We are validating the second and third word to make sure
  62.     */
  63.     if (sscanf (str,"%s %s %s %s",ipstr,mbps,ethernet,hwstr)==4){
  64.         if (strcmp(mbps,"10Mbps")!=0
  65.             || strcmp(ethernet,"Ethernet")!=0){
  66.             xconf_error (MSG_U(E_IVLDRARPFORM
  67.                 ,"Invalid format in file %s, line %d")
  68.                 ,f_net_rarp.getpath(),noline);
  69.         }else{
  70.             ip.setfrom (ipstr);
  71.             hw.setfrom (hwstr);
  72.         }
  73.     }
  74. }
  75.  
  76. /*
  77.     Constructor used to read configuration.
  78. */
  79. PUBLIC RARP_ENTRY::RARP_ENTRY(
  80.     const char *_ip,
  81.     const char *_hw,
  82.     int _active,
  83.     const char *_comment)
  84. {
  85.     seen = 0;
  86.     ip.setfrom (_ip);
  87.     hw.setfrom (_hw);
  88.     active = (char)_active;
  89.     comment.setfrom (_comment);
  90.     normalise();
  91. }
  92.  
  93. /*
  94.     Create an empty entry
  95. */
  96. PUBLIC RARP_ENTRY::RARP_ENTRY()
  97. {
  98.     seen = 0;
  99.     active = 1;
  100. }
  101.  
  102. /*
  103.     Add this entry to the rarp table
  104. */
  105. PUBLIC int RARP_ENTRY::set()
  106. {
  107.     char buf[200];
  108.     sprintf (buf,"-s %s %s",ip.get(),hw.get());
  109.     return netconf_system_if ("rarp",buf);
  110. }
  111.  
  112. /*
  113.     Compare one IP number with this entry
  114.     Return 0 if equal, != 0 if different.
  115. */
  116. PUBLIC int RARP_ENTRY::cmp(const char *ipstr)
  117. {
  118.     int ret = ip.cmp(ipstr);
  119.     if (ret != 0){
  120.         /* #Specification: rarp / entry / ip or host name
  121.             We can specify a host either by its IP number
  122.             or its host name.
  123.         */
  124.         struct hostent *ent = gethostbyname(ip.get());
  125.         if (ent != NULL){
  126.             char str[20];
  127.             devices_ip2a (ent,str);
  128.             ret = strcmp(ipstr,str);
  129.         }
  130.     }
  131.     return ret;
  132. }
  133.  
  134.  
  135.  
  136. /*
  137.     delete this entry from the rarp table
  138. */
  139. PUBLIC int RARP_ENTRY::unset ()
  140. {
  141.     char buf[200];
  142.     sprintf (buf,"-d %s",ip.get());
  143.     return netconf_system_if ("rarp",buf);
  144. }
  145.  
  146.  
  147. class RARP_ENTRIES: public ARRAY{
  148.     /*~PROTOBEG~ RARP_ENTRIES */
  149. public:
  150.     RARP_ENTRIES (CONFIG_FILE&f);
  151.     RARP_ENTRIES (void);
  152.     void edit (void);
  153.     RARP_ENTRY *getitem (int no);
  154.     int isoneactive (void);
  155.     RARP_ENTRY *locate (const char *ipstr);
  156.     int save (void);
  157.     void update (RARP_ENTRIES¤t);
  158.     /*~PROTOEND~ RARP_ENTRIES */
  159. };
  160.  
  161. PUBLIC RARP_ENTRY *RARP_ENTRIES::getitem (int no)
  162. {
  163.     return (RARP_ENTRY*)ARRAY::getitem(no);
  164. }
  165.  
  166. /*
  167.     Locate an entry using its IP number or name.
  168.     Only active entries are checked.
  169. */
  170. PUBLIC RARP_ENTRY *RARP_ENTRIES::locate (const char *ipstr)
  171. {
  172.     RARP_ENTRY *ret = NULL;
  173.     for (int i=0; i<getnb(); i++){
  174.         RARP_ENTRY *a = getitem(i);
  175.         if (a->active && a->cmp(ipstr)==0){
  176.             ret = a;
  177.             break;
  178.         }
  179.     }
  180.     return ret;
  181. }
  182.  
  183. static char RARP[]="rarp";
  184. static char ENTRY[]="entry";
  185. /*
  186.     Load from /etc/conf.linuxconf
  187. */
  188. PUBLIC RARP_ENTRIES::RARP_ENTRIES()
  189. {
  190.     SSTRINGS strs;
  191.     linuxconf_getall (RARP,ENTRY,strs,0);
  192.     int nb = strs.getnb();
  193.     for (int i=0; i<nb; i++){
  194.         SSTRING *s = strs.getitem(i);
  195.         char ipstr[200],hwstr[200],acstr[200];
  196.         const char *pt = s->get();
  197.         pt = str_copyword (ipstr,pt);
  198.         pt = str_copyword (hwstr,pt);
  199.         pt = str_copyword (acstr,pt);
  200.         // The active field has been added. It defaults to "active"
  201.         int active = acstr[0] == '\0' ? 1 : atoi(acstr) != 0;
  202.         pt = str_skip(pt);
  203.         sscanf (s->get(),"%s %s",ipstr,hwstr);
  204.         add (new RARP_ENTRY (ipstr,hwstr,active,pt));
  205.     }
  206.     rstmodified();
  207. }
  208.  
  209. /*
  210.     Update /etc/conf.linuxconf
  211. */
  212. PUBLIC int RARP_ENTRIES::save()
  213. {
  214.     int n = getnb();
  215.     linuxconf_removeall (RARP,ENTRY);
  216.     for (int i=0; i<n; i++){
  217.         RARP_ENTRY *e = getitem(i);
  218.         char buf[400];
  219.         sprintf (buf,"%s %s %d %s",e->ip.get(),e->hw.get(),e->active
  220.             ,e->comment.get());
  221.         linuxconf_add (RARP,ENTRY,buf);
  222.     }
  223.     rstmodified();
  224.     return linuxconf_save();
  225. }
  226.  
  227. /*
  228.     Load the running config.
  229. */
  230. PUBLIC RARP_ENTRIES::RARP_ENTRIES(CONFIG_FILE &f)
  231. {
  232.     FILE *fin = f.fopen ("r");
  233.     if (fin != NULL){
  234.         int noline = 1;
  235.         char buf[300];
  236.         // Skip the first line
  237.         fgets (buf,sizeof(buf)-1,fin);
  238.         while (fgets (buf,sizeof(buf)-1,fin) != NULL){
  239.             noline++;
  240.             add (new RARP_ENTRY(buf,noline));
  241.         }
  242.         fclose (fin);
  243.     }
  244. }
  245.  
  246.  
  247. PUBLIC void RARP_ENTRIES::update (RARP_ENTRIES ¤t)
  248. {
  249.     int n = current.getnb();
  250.     int i;
  251.     for (i=0; i<n; i++){
  252.         RARP_ENTRY *cur_a = current.getitem(i);
  253.         RARP_ENTRY *a = locate (cur_a->ip.get());
  254.         if (a == NULL){
  255.             cur_a->unset();
  256.         }else{
  257.             a->seen = 1;
  258.             if (a->hw.cmp(cur_a->hw)!=0){
  259.                 cur_a->unset(); 
  260.                 a->set(); 
  261.             }
  262.         }
  263.     }
  264.     n = getnb();
  265.     for (i=0; i<n; i++){
  266.         RARP_ENTRY *a = getitem(i);
  267.         if (!a->seen && a->active) a->set();
  268.     }
  269. }
  270.  
  271. /*
  272.     Validate and normalise the format of the hardware address.
  273.     Make sure there is 2 digits per byte. This helps when comparing
  274.     with the current setup as read from /proc/net/rarp.
  275. */
  276. PRIVATE int RARP_ENTRY::normalise()
  277. {
  278.     int digits[6];
  279.     memset (digits,0,sizeof(digits));
  280.     const char *pt = hw.get();
  281.     int err = 0;
  282.     int nbhex = 0;
  283.     int nbpt = 0;
  284.     while (*pt != '\0'){
  285.         char carac = *pt++;
  286.         if (carac == ':'){
  287.             if (nbhex == 0 || nbhex > 2) err = 1;
  288.             nbhex = 0;
  289.             nbpt++;
  290.         }else if (nbpt == 6){
  291.             err = 1;
  292.         }else if (isxdigit(carac)){
  293.             digits[nbpt] *= 16;
  294.             if (isalpha(carac)){
  295.                 carac = toupper(carac) - 'A' + 10;
  296.             }else{
  297.                 carac -= '0';
  298.             }
  299.             digits[nbpt] += carac;
  300.             nbhex++;
  301.         }else{
  302.             err = 1;
  303.         }
  304.     }
  305.     if (nbpt != 5 || nbhex == 0){
  306.         err = 1;
  307.     }else{
  308.         char formstr[6*2+5+0];
  309.         sprintf (formstr,"%02x:%02x:%02x:%02x:%02x:%02x"
  310.             ,digits[0],digits[1],digits[2],digits[3],digits[4],digits[5]);
  311.         hw.setfrom (formstr);
  312.     }
  313.     return err ? -1 : 0;
  314. }
  315.  
  316. /*
  317.     Return != 0 the entry is valid.
  318.     May operate silently or show errors
  319. */
  320. PUBLIC int RARP_ENTRY::is_valid(int talk)
  321. {
  322.     int ret = 0;
  323.     if (ip.is_empty() || hw.is_empty()){
  324.         if (talk) xconf_error (MSG_U(E_ALLFIELD,"All field must be filled"));
  325.     }else{
  326.         if (normalise()==-1){
  327.             if (talk){
  328.                 xconf_error (MSG_U(E_HARDETH
  329.                     ,"Invalid hardware ethernet address\n"
  330.                      "%s\n"
  331.                      "Expect xx:xx:xx:xx:xx:xx format")
  332.                     ,hw.get());
  333.             }
  334.         }else{
  335.             ret = 1;
  336.         }
  337.     }
  338.     return ret;
  339. }
  340. /*
  341.     Edit one entry
  342.     Return -1 if the user cancel
  343.     Return  0 if the user accept the changes
  344.     Return  1 if the user wish to delete this record
  345. */
  346. PUBLIC int RARP_ENTRY::edit()
  347. {
  348.     int ret = -1;
  349.     DIALOG dia;
  350.     dia.newf_chk ("",active,MSG_U(F_RARPACTIVE,"This record is active"));
  351.     dia.newf_str (MSG_U(F_HOSTNAME,"host name or IP number"),ip);
  352.     dia.newf_str (MSG_U(F_ETHADR,"Ethernet address"),hw);
  353.     dia.newf_str (MSG_R(F_COMMENT),comment);
  354.     int nof = 0;
  355.     while (1){
  356.         MENU_STATUS code = dia.edit(MSG_U(T_ETH2IP,"Ethernet to IP translation")
  357.             ,MSG_U(I_ETH2IP
  358.              ,"Enter an IP number or a host name\n"
  359.               "and its ethernet 6 hexadecimal digit\n"
  360.               "address")
  361.             ,help_rarp
  362.             ,nof
  363.             ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL);
  364.         if (code == MENU_CANCEL || code == MENU_ESCAPE){
  365.             break;
  366.         }else if (code == MENU_DEL){
  367.             ret = 1;
  368.             break;
  369.         }else if (is_valid(1)){
  370.              ret = 0;
  371.             break;
  372.         }
  373.     }
  374.     if (ret != 0) dia.restore();
  375.     return ret;
  376. }
  377.  
  378. static int cmp_by_ip (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2)
  379. {
  380.     RARP_ENTRY *e1 = (RARP_ENTRY*)o1;
  381.     RARP_ENTRY *e2 = (RARP_ENTRY*)o2;
  382.     return e1->ip.cmp(e2->ip);
  383. }
  384.  
  385. PUBLIC void RARP_ENTRIES::edit()
  386. {
  387.     int choice = 0;
  388.     while (1){
  389.         DIALOG dia;
  390.         sort (cmp_by_ip);
  391.         for (int i=0; i<getnb(); i++){
  392.             RARP_ENTRY *e = getitem(i);
  393.             char buf1[30],buf2[100];
  394.             sprintf (buf1,"[%c] %s",e->active ? 'X' : ' ',e->ip.get());
  395.             sprintf (buf2,"%s %s",e->hw.get(),e->comment.get());
  396.             dia.new_menuitem (buf1,buf2);
  397.         }
  398.         dia.addwhat (MSG_U(I_ANEWENTRY,"a new entry"));
  399.         MENU_STATUS code = dia.editmenu(
  400.             MSG_U(T_RARPCONF,"RARP configuration")
  401.             ,MSG_U(I_RARPCONF,"You are allowed to edit/add\n"
  402.               "RARP (Reverse Address Resolution)\n"
  403.               "which will allow other computer to get\n"
  404.               "their IP number from this server\n")
  405.             ,help_rarp
  406.             ,choice
  407.             ,0);
  408.         if (code == MENU_ESCAPE || code == MENU_QUIT){
  409.             break;
  410.         }else if (perm_rootaccess(MSG_U(P_EDITRARP
  411.             ,"to edit RARP configuration"))){
  412.             if (code == MENU_ADD){
  413.                 RARP_ENTRY *e = new RARP_ENTRY;
  414.                 if (e->edit () == 0){
  415.                     add (e);
  416.                     save();
  417.                 }else{
  418.                     delete e;
  419.                 }
  420.             }else if (choice >= 0 && choice < getnb()){
  421.                 RARP_ENTRY *e = getitem(choice);
  422.                 if (code == MENU_OK){
  423.                     int ok = e->edit();
  424.                     if (ok >= 0){
  425.                         if (ok == 1) remove_del (e);
  426.                         save();
  427.                     }
  428.                 }
  429.             }
  430.         }
  431.     }
  432. }
  433. /*
  434.     Return != 0 if there is at least one record active
  435. */
  436. PUBLIC int RARP_ENTRIES::isoneactive()
  437. {
  438.     int ret = 0;
  439.     int n = getnb();
  440.     for (int i=0; i<n; i++){
  441.         RARP_ENTRY *e = getitem(i);
  442.         if (e->active){
  443.             ret = 1;
  444.             break;
  445.         }
  446.     }
  447.     return ret;
  448. }
  449.  
  450. /*
  451.     Edit the RARP table used to program the kernel RARP table
  452. */
  453. void rarp_edit()
  454. {
  455.     RARP_ENTRIES rarps;
  456.     rarps.edit();
  457. }
  458.  
  459.  
  460. /*
  461.     Install, update the rarp table
  462. */
  463. void rarp_activate ()
  464. {
  465.     if (perm_rootaccess(MSG_U(P_UPDRARP,"to install RARP entry"))){
  466.         RARP_ENTRIES conf;
  467.         if (f_net_rarp.exist()){
  468.             RARP_ENTRIES cur (f_net_rarp);
  469.             conf.update (cur);
  470.         }else if (conf.isoneactive()){
  471.             /* #Specification: rarp / module
  472.                 If /proc/net/rarp is not available, the command
  473.                 "modprobe rarp" is executed to load the module.
  474.                 The presence of /proc/net/rarp is checked again
  475.                 to see if it has succeeded. An error message is
  476.                 generated.
  477.  
  478.                 This is done only if some rarp entries are
  479.                 configured.
  480.             */
  481.             netconf_system_if ("modprobe","rarp");
  482.             if (f_net_rarp.exist()){
  483.                 RARP_ENTRIES cur (f_net_rarp);
  484.                 conf.update (cur);
  485.             }else{
  486.                 xconf_error (MSG_U(E_NORARP
  487.                     ,"This kernel does not support RARP\n"
  488.                      "I can't load the RARP table\n"
  489.                      "Some machines may fail to boot because of that"));
  490.             }
  491.         }
  492.     }
  493. }
  494.